package bachelor.view {
	import CustomEvent.CustomEvent;

	import app.core.action.RotatableScalable;

	import bachelor.Globals;
	import bachelor.datamanagement.XMLLoader;

	import fiducialTuioAS3.tuio.TouchEvent;

	import gs.TweenLite;
	import gs.easing.Strong;

	import flash.display.MovieClip;
	import flash.events.Event;

	/** ABLAUF
	 * ======================================================
	 *         Constructor
	 *             ↓
	 *             ↓
	 *       keywordActivated   
	 *             ↓
	 *             ↓
	 *        loadImagePath  → → → → → XMLLoader
	 *                                    ↓
	 *                                    ↓
	 *      onXMLLoadedHander ← ←  ← ←  Event
	 *             ↓
	 *             ↓
	 *        initAllLayer → → → → → →  Layer  → → → → Pic
	 *                                                  ↓
	 *                                                  ↓
	 * onLastLayerLoadedHandler ← ← ← ← Layer  ← ← ← Event
	 *             ↓
	 *             ↓
	 *       GUI > initInterface
	 *       GUI > initScala 
	 *		  moveLayers
	 * ======================================================
	 */
	public class Country extends MovieClip  
	{


////////////////////////////////////////////////////////////////////////////////
/////// VARIABLES //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
		private var _id : int;
		
		// Layoutarrangement
		private var _xOffset : int = -105;
		private var _yOffset : int = -115;
		private var _startRotation : int;
		private var _tintColor : uint;
		private var _tintColorIndex : int;
		// TODO: Buttons mit Grid verbinden
		private var _activeGrid : int = 4;
	
		private var _activatedKeywordID : int;

		private var _myXMLLoader 	: XMLLoader;
		private var _loadingState	: Boolean = false;
		
		private var _interface 	: MovieClip = new MovieClip();

		
		private var _layerArray	: Array = new Array();
		private var _loadedLayerCounter : int = 0;

		private var _gridButton1  : GridButton;
		private var _gridButton4  : GridButton;
		private var _gridButton16 : GridButton;

		// Events
		public static const LAYERS_ADDED : String = "layersAdded";
		public static const COUNTRY_DEINITIALIZED : String = "countryDeinitialized";
		

////////////////////////////////////////////////////////////////////////////////
/////// CONSTRUCTOR ////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////		
		public function Country(p_id : int, p_startRotation : Number, p_tintColorIndex : int, p_activeKeywordID : int) 
		{			
			trace("Country -> Constructor init... für Country no " + p_id);
			
			_activatedKeywordID = p_activeKeywordID;
			
			_id = p_id;
			/*
			 * Die Start-Rotation muss bei der Scala-Rotation miteinberechnet werden
			 */
			_startRotation = Math.round(p_startRotation);
			/*
			 * Farbe-Index im Array für onRemove zwischenspeichern
			 */
			_tintColorIndex = p_tintColorIndex;
			_tintColor = Globals.countryColorArray[p_tintColorIndex][1];
			// TODO: Hilfsgrafik entfernen
			var tempBG : MovieClip = new MovieClip();
			tempBG.graphics.beginFill(0xeaeaea);
			tempBG.graphics.drawRect(-125, -125, 250, 250);
			tempBG.graphics.endFill();
			tempBG.alpha = 0.1;
			addChild(tempBG);
			
			/*
			 * Land wird erst erstellt, wenn Keyword schon gelegt ist.
			 * Deshalb sofort die XML laden und anschließend die Layers und Pics.
			 */
			loadImagePaths(_activatedKeywordID);

		}
		
		
		
////////////////////////////////////////////////////////////////////////////////
/////// METHODS ////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
/////// KEYWORD ACTIVATED / DEACTIVATED ////////////////////////////////////////


/////// Keyword aktiviert //////////////////////////////////////////////////////
//		public function keywordActivated(p_activeKeywordID : int) : void 
//		{
//			trace("Country -> keywordActivated() ...");
//			loadImagePaths(p_activeKeywordID);
//		}


/////// Land ausblenden, dann löschen //////////////////////////////////////////
		public function deinitializeCountry() : void 
		{
			trace("Country -> deinitializeCountry() ...");
			hideAllLayers();
			hideInterface();
		}

		
////////////////////////////////////////////////////////////////////////////////
/////// XML LADEVORGANG ////////////////////////////////////////////////////////


/////// XML laden ////////////////////////////////////////////////////////
		private function loadImagePaths(p_activeKeywordID : int) : void
		{
			// TODO: XML-Pfad dynamisch über _globals.countryArray und dem aktuellen Thema generieren 
			trace("Country -> loadImages() ...");
			var XMLPath : String = "bin/pics/" + Globals.keywordArray[p_activeKeywordID][0] + "/country" + Globals.countryArray[_id][1] + "/data" + Globals.countryArray[_id][1] + ".xml";			
			_myXMLLoader = new XMLLoader(XMLPath, this);
			_myXMLLoader.addEventListener(XMLLoader.XML_LOADED, onXMLLoadedHandler);
			
		}

/////// XML fertig /////////////////////////////////////////////////////////////
		private function onXMLLoadedHandler(evt : CustomEvent) : void
		{
			trace("Country -> onXMLLoaderHandler() ...");
			var myCompletedXMLLoader : XMLLoader = evt.target as XMLLoader;
			myCompletedXMLLoader.removeEventListener(XMLLoader.XML_LOADED, onXMLLoadedHandler);
			initAllLayers(evt.data as XML);
		}

////////////////////////////////////////////////////////////////////////////////
/////// INITs //////////////////////////////////////////////////////////////////


/////// INIT All-Layers /////////////////////////////////////////
		public function initAllLayers(p_myXML : XML) : void
		{
			trace("Country -> initAllLayers() init...");
			/*
			 * Falls das Country während des Ladens schon wieder entfernt wird, 
			 * muss das Entfernen durch die GUI anders passieren.
			 */
			_loadingState = true;
			/*
			 * Erstellt entsprechend des aktuellen Grids 
			 * die benötige Anzahl der Layers inkl. der Pics 
			 * innerhalb des SlideshowMCs
			 */
			for(var i:int = (48/_activeGrid); i > 0; i--) 
			{
//				trace("Country -> initAllLayers() ::: erstelle Layer " + _layerArray.length);
				
				var newLayer : Layer = newLayer = new Layer(p_myXML, i, _activeGrid);
				// TODO: Perspektive via 3D lösen
				/*
				 * Layer perspektivisch sehr weit hinten erstellen
				 */
				newLayer.x = get3DLook("x", i); 
				newLayer.y = get3DLook("y", i);
				newLayer.scaleX = get3DLook("scale", i); 
				newLayer.scaleY = get3DLook("scale", i);
				newLayer.alpha = 0;

				newLayer.addEventListener(Layer.SINGLE_LAYER_LODED, onSingleLayerLoadedHandler);
				/*
				 * Layer vorne im Layer-Array einfügen
				 */ 
				_layerArray.unshift(newLayer);
				addChild(newLayer);

				newLayer.addEventListener(Layer.CREATE_BOOKMARK, createBookmarkHandler);
			}
		}
		
/////// DEINIT All-Layers //////////////////////////////////////////////////////
		private function hideAllLayers() : void 
		{
			trace("Country -> hideAllLayers() ...");
			
			/*
			 * Alle Layers von der Bühne entfernen
			 */
			for(var i:int = 0; i < _layerArray.length; i++)
			{
				// TODO: TweenLite -> onComplete deinitIntreface
				
				var layerToRemove : Layer = _layerArray[i] as Layer;
				/*
				 * Layer darf bei fertigem Laden, nicht mehr mitgezählt werden.
				 */
				layerToRemove.removeEventListener(Layer.SINGLE_LAYER_LODED, onSingleLayerLoadedHandler);
				removeChild(layerToRemove);
			}
			/*
			 * Inhalte löschen wegen Performance
			 */
			_layerArray = [];
			_loadedLayerCounter = 0;
			
			
		}

		
/////// Bilder fertig geladen, jetzt Elemente einblenden ///////////////////////
		private function onSingleLayerLoadedHandler(evt : Event) : void 
		{
			var singleLoadedLayer : Layer = evt.target as Layer;
			singleLoadedLayer.removeEventListener(Layer.SINGLE_LAYER_LODED, onSingleLayerLoadedHandler);

			/*
			 * Bei jeder geladenen Layer, mitzählen
			 */
			_loadedLayerCounter++;
			trace("Country -> onSingleLayerLoadedHandler() ... " + _loadedLayerCounter);
			
			/*
			 * Wenn alle Layer geladen sind, darf es grafisch weitergehen
			 */
			if(_loadedLayerCounter >= (48 / _activeGrid))
			{
				/*
				 * Lade-Status wieder auf false setzen, 
				 * ist beim Entfernen des Landes wichtig
				 */
				_loadingState = false;
				/*
				 * Interface einblenden
				 */
				initInterface();
				/*
				 * Scala einblenden
				 */
				dispatchEvent(new Event(LAYERS_ADDED));
				/*
				 * Layers erstmalig hereinfahren und erste Ebene (0) klickbar machen 
				 */ 
				moveLayers(0, -1);
			}			
		}

		
/////// INIT Interface /////////////////////////////////////////////////////////
		private function initInterface() : void
		{
			trace("Country -> initInterface() ...");
			_interface.x = _xOffset;
			_interface.y = _yOffset;
			addChild(_interface);
	
			var _panel : MovieClip = MovieClip(new panelMC());
			_panel.x = 0;
			_panel.y = 0;
			_interface.addChild(_panel);

			///// BUTTONS //////
//			Erstelle die 3 Buttons je mit BitMaps und Methoden für seine eigene grafische Darstellung
 			_gridButton1 = new GridButton(1); 
			_gridButton1.x = -195 - _xOffset;
			_gridButton1.y = 17 - _yOffset;
			_gridButton1.addEventListener(TouchEvent.MOUSE_UP, gridButtonPressedHandler);
			_interface.addChild(_gridButton1);

 			_gridButton4 = new GridButton(4);
			_gridButton4.x = -165 - _xOffset;
			_gridButton4.y = 17 - _yOffset;
			_gridButton4.addEventListener(TouchEvent.MOUSE_UP, gridButtonPressedHandler);
			_interface.addChild(_gridButton4);

 			_gridButton16 = new GridButton(16);
			_gridButton16.x = -135 - _xOffset;
			_gridButton16.y = 17 - _yOffset;
			_gridButton16.addEventListener(TouchEvent.MOUSE_UP, gridButtonPressedHandler);
			_interface.addChild(_gridButton16);
			
		}


/////// DEINIT Interface ///////////////////////////////////////////////////////
		private function hideInterface() : void 
		{
			trace("Country -> hideInterface() ...");
			TweenLite.to(_interface, Globals.fadeOutTime, {alpha: 0, ease:Strong.easeOut, onComplete: onCountryDeinitialized});
		}
		
/////// Country fertig ausgeblendet ////////////////////////////////////////////
		private function onCountryDeinitialized() : void 
		{
			trace("Country -> onCountryDeinitialized() ...");
			dispatchEvent(new Event(COUNTRY_DEINITIALIZED));
			removeChild(_interface);
		}





////////////////////////////////////////////////////////////////////////////////
/////// moveLayers /////////////////////////////////////////////////////////////
		public function moveLayers(p_currentLayerIndex : int, p_lastLayerIndex : int) : void 
		{						//  p_currentLayerIndex = Index des aktuell angezeigten Layers
		
//			trace("Country -> moveLayers() ::: p_currentLayerIndex = " + p_currentLayerIndex);
			/*
			 *  Abfragen, ob schon alle Layers erstellt sind
			 */
			if(_layerArray.length >= (48 / _activeGrid)) 
			{
				
				for(var i:int = (48/_activeGrid); i > 0; i--)  
				{
					var newY		: Number = get3DLook("y", (i - p_currentLayerIndex));
					var newScaleX 	: Number = get3DLook("scale", (i - p_currentLayerIndex));
					var newScaleY 	: Number = get3DLook("scale", (i - p_currentLayerIndex));
					var newAlpha	: Number = get3DLook("alpha", (i - p_currentLayerIndex));
					
					var layerToMove	: Layer = _layerArray[i-1] as Layer;
					
					layerToMove.scaleX = newScaleX;
					layerToMove.scaleY = newScaleY;
					layerToMove.y = newY;
					layerToMove.alpha = newAlpha;
					if((i - p_currentLayerIndex) >= 0) {
						layerToMove.visible = true;
					} else 
					{
						layerToMove.visible = false;
					}
					
										
//					TODO: Tweenen (VORSICHT fehlerhaft!)
//					TweenMax.to(layerToMove, 1, {
//						scaleX: 	newScaleX, 
//						scaleY: 	newScaleY, 
//						y: 			newY,
//						alpha: 		newAlpha, 
//						ease:Strong.easeOut, 
//						overwrite: 2
//					});	
					
					// clickalbe Layer vertauschen
					
					// FIXME: Entsprechende Ebenen korrekt ansprechen
					if(i == p_currentLayerIndex+1) 
					{
						layerToMove.makeClickable();
					}
					
					if(i == p_lastLayerIndex) {
						layerToMove.makeUnclickable();
					}


				}
				
				
			}

					
		}
		
		
		
		
		

			
			

////////////////////////////////////////////////////////////////////////////////
/////// BUTTONS ////////////////////////////////////////////////////////////////

/////// Grid-Button gedrückt ///////////////////////////////////////////////////
		private function gridButtonPressedHandler(evt : TouchEvent) : void {
			trace("============ Button Prssed === evt.target === " + evt.target);
//			switch(evt.target._id) 
//			{
//				case 1:
//					trace("Jetzt wird ins Grid 1 gewechselt");
//					break;
//				case 4:
//					trace("Jetzt wird ins Grid 4 gewechselt");
//					break;
//				case 16:
//					trace("Jetzt wird ins Grid 16 gewechselt");
//					break;
//			}
		}
			
		// TODO: Button-Funktionalitäten herstellen
// 		private function btnPressed(e:Event) : void 
//		{
//			// e.target = _myBtn1 ODER _myBtn2 ODER _myBtn3
//			entsperreAlleButtons();
// 			e.target.makeMeUntouchable();
//			removeAllLayers();
// 			_activeGrid = e.target.id;
//			initAllLayers(//param);
//		}
//
//		private function entsperreAlleButton() :void {
//			_myBtn1.makeMeTouchable();
//			_myBtn2.makeMeTouchable();
//			_myBtn3.makeMeTouchable();
//		}
//
//		private Function removeAllLayers() {
//			// Leere das Array layerArray
//		}






////////////////////////////////////////////////////////////////////////////////
/////// BOOKMARKS //////////////////////////////////////////////////////////////
		
		private function createBookmarkHandler(evt : CustomEvent) : void 
		{
			var dataArray : Array = evt.data as Array;
			
			var newBookmark : Bookmark = new Bookmark(dataArray[0], dataArray[1], _tintColor);
			newBookmark.x    		= dataArray[2] + dataArray[3];
			newBookmark.y   		= dataArray[4] + dataArray[5];
			newBookmark.scaleX    	= dataArray[6];
			newBookmark.scaleY		= dataArray[7];
			newBookmark.rotation 	= dataArray[8];
			addChild(newBookmark);
//			newBookmark.addEventListener(TouchEvent.MOUSE_DOWN, bookmarkMouseDownHandler);
			newBookmark.addEventListener(Bookmark.START_FADING_OUT, bookmarkOnStartFadingOut);
			this.setChildIndex(newBookmark, 0);
		}
		
		private function bookmarkFingerUpHandler(evt : Event) : void 
		{
			trace("=1 Country -> bookmarkFingerUpHandler() ...");
			var touchedBookmark : Bookmark = evt.currentTarget as Bookmark;
			touchedBookmark.startFadingOutTimer();
			touchedBookmark.removeEventListener(RotatableScalable.FINGER_UP, bookmarkFingerUpHandler);
			touchedBookmark.addEventListener(Bookmark.START_FADING_OUT, bookmarkOnStartFadingOut);
			trace("=======AKTUELLER SCALE: " + touchedBookmark.scaleX);
			touchedBookmark.setScaleVal(touchedBookmark.scaleX);
		}

		private function bookmarkOnStartFadingOut(evt : Event) : void 
		{
			
			trace("=4 Country -> bookmarkOnStartFadingOut() ...");
			var fadingOutBookmark : Bookmark = evt.currentTarget as Bookmark;
			fadingOutBookmark.addEventListener(TouchEvent.MOUSE_DOWN, bookmarkMouseDownHandler);
			fadingOutBookmark.removeEventListener(Bookmark.START_FADING_OUT, bookmarkOnStartFadingOut);
			TweenLite.to(fadingOutBookmark, 5, {scaleX: 0, scaleY: 0, alpha: 0, ease:Strong.easeIn});
		}
		
		private function bookmarkMouseDownHandler(evt : TouchEvent) : void 
		{
			trace("=5 Country -> bookmarkMouseDownHandler() ...");
			var fadingOutBookmark : Bookmark = evt.currentTarget as Bookmark;
			var newScale : Number;
			if(fadingOutBookmark.getScaleVal()) {
				newScale = fadingOutBookmark.getScaleVal();
			} else 
			{
				newScale = 1;	
			}
			trace("=======NEW SCALE: " + newScale);
			TweenLite.to(fadingOutBookmark, 0.5, {scaleX: newScale, scaleY: newScale, alpha: 1, ease:Strong.easeIn});
			fadingOutBookmark.addEventListener(RotatableScalable.FINGER_UP, bookmarkFingerUpHandler);
			fadingOutBookmark.stopFadingOutTimer();
		}

		
		
////////////////////////////////////////////////////////////////////////////////
/////// HELPERS ////////////////////////////////////////////////////////////////


/////// 3D-Berechnungen ////////////////////////////////////////////////////////
		private function get3DLook(p_attribute : String, p_layerID : int) : Number
		{

			var new3DFactor : Number = 1 / Math.sqrt(Math.sqrt(p_layerID));
			new3DFactor = Math.floor(new3DFactor * 100) / 100; 
			
			var returnVar : Number;
			
			switch(p_attribute)
			{
				case "scale":
					if(p_layerID >= 0) 
					{
						returnVar = new3DFactor;
					} else 
					{
						returnVar = 2;
					}
					break;
				case "x":
					returnVar = _xOffset + 0;
					break;
				case "y": 
					if(p_layerID >= 0) 
					{
						returnVar = (200 * new3DFactor) - 200 + _yOffset;
					} else 
					{
						returnVar = -200 + _yOffset;
					}
					break;
				case "alpha":
					if(p_layerID >= 0) 
					{
						returnVar = Math.pow(new3DFactor, 3);
					} else 
					{
						returnVar = 0.05;
					}
					break;
			}
			return returnVar;
		}
		



////////////////////////////////////////////////////////////////////////////////
/////// getters & setters //////////////////////////////////////////////////////


/////// TintColor-Index für onRemove zurückgeben ///////////////////////////////
		public function getTintColorIndex() : int 
		{
			return _tintColorIndex;
		}


/////// ID zurückgeben /////////////////////////////////////////////////////////
		public function getID() : int 
		{
			return _id;
		}

/////// Ladestatus beim Entfernen zurückgeben //////////////////////////////////
		public function getLoadingState() : Boolean 
		{
			return _loadingState;
		}


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
	}
}
